#!/bin/bash
#
# Authors: 
#   Danilo Riffo (aka. DanAlucard)       danriffo (at) gmail.com
#   Fabrice Bauzac                       libnoon (at) gmail.com
#
# License: GPL v3
#
# made for own usage and for the WineHQ - League of Legends community
#
#
#################################################################################
####
####  For help, issue the following command:
####  ./install-LoL-on-Wine -h
####
#################################################################################

# This variable stores the location for the custom-compiled wine and the
# wineprefix (virtual Windows installation) used to run the game on Linux. 
# By default it is your home directory.
Install_Location="${HOME}"

# change this to the specific wine version you want to use. 
# I recommend using 1.7.20, but it's up to you.
Wine_version="1.7.20"

# assign any value to migrate a working installation previously made using this 
# same script to the version of wine specified above.
#
# MigrationFlag="1"
# MigrationFlag="united states is not america"
#
# are examples. Any data is good, so it isn't empty :D
MigrationFlag=""

# if you have an already working LoL installation somewhere, type here the absolute path
# to the "Riot Games" folder, so the script can copy it and don't fully install LoL again :D
# 
# Example:
#
# Existing_LoL_Installation="/mnt/WindozePartition/Riot Games"
# 
Existing_LoL_Installation=""

progname="Install-LoL-on-Wine"

version () {
    echo "$progname version 2.1"
}

print_report_issues () {
    echo "Report issues at:"
    echo "https://code.google.com/p/league-of-legends-on-wine-install-script/issues/list"
}

usage () {
    echo "$progname [OPTION...] WINEVERSION INSTALLER"
    echo "Install the League of Legends software."
    echo "WINEVERSION is the Wine version to install, (e.g. 1.7.0)."
    echo "INSTALLER should be the absolute path to the LoL installer Windows executable."
    echo " Options:"
    echo "   -i INSTALLPATH  Base directory for the installation (default: \$HOME)."
    echo "   -r PATH         Path to an existing and working LoL installation."
    echo "                   It should be the path to the 'Riot Games' directory."
    echo "   -m              Just rebuild Wine and recreate the launcher, keeping the rest as it is."
    echo "                   The current installation must have been done by $progname."
    echo "   -h              Show this help."
    echo "   -v              Print version information."
    print_report_issues
}

while getopts hr:mi:v opt
do
    case "$opt" in
	v)
	    version
	    exit 0
	    ;;
	i)
	    Install_Location="$OPTARG"
	    if ! [ -d "$OPTARG" ]
	    then
		echo "directory $OPTARG does not exist" 1>&2
		exit 1
	    fi
	    ;;
	h)
	    usage
	    exit 0
	    ;;
	m)
	    MigrationFlag=1
	    ;;
	r)
	    Existing_LoL_Installation="$OPTARG"
	    if ! [ -d "$OPTARG" ]
	    then
		echo "directory $OPTARG does not exist" 1>&2
		exit 1
	    fi
	    ;;
	'?')
	    exit 1
	    ;;
	*)
	    echo "unhandled option {$opt}" 1>&2
	    exit 1
	    ;;
    esac
done
shift "`expr $OPTIND - 1`"

# There should be two arguments left: WINEVERSION INSTALLER.
if [ "$#" -lt 2 ]
then
    echo "missing argument" 1>&2
    exit 1
elif [ "$#" -gt 2 ]
then
    echo "too many arguments" 1>&2
    exit 1
fi
Wine_version="$1"
LoL_Installer_Location="$2"

# Prompt the user for continuing or quitting.
ok_or_quit () {
    cont=true
    while $cont
    do
	printf "Type [c] to continue, [q] to quit: "
	read line
	case "$line" in
	    c)
		cont=false
		;;
	    q)
		exit 0
		;;
	    *)
		echo "invalid input: {$line}" 1>&2
		;;
	esac
    done
}

#################################################################################
#variable that we will need to compile and configure wine                       #
#################################################################################
wineinstall="$Install_Location/LoL_wine-$Wine_version"
export WINEPREFIX="$Install_Location/LoL_Prefix"            #wineprefix's location
launchscript="$HOME/Desktop/Play_LeagueOfLegends.sh"

# Print a summary of the settings.
echo "Base installation directory: $Install_Location"
echo "Will download Wine version: $Wine_version"
echo "Will install Wine into: $wineinstall"
echo "Wine prefix directory: $WINEPREFIX"
echo "LoL launch script location: $launchscript"
printf "Migration mode (i.e. just rebuild Wine and recreate the launcher): "
if [ -z "$MigrationFlag" ]
then
    echo "no"
else
    echo "yes"
fi
printf "Existing LoL installation: "
if [ -z "$Existing_LoL_Installation" ]
then
    echo "no"
else
    echo "$Existing_LoL_Installation"
fi
echo "LoL installer: $LoL_Installer_Location"
print_report_issues

ok_or_quit
echo "OK, continuing..."

#################################################################################
####                                                                            #
#### These are some dependency tests, don't touch them.                         #
#### If you can't compile wine properly I'm not gonna let you try ;)            #
####                                                                            #
#################################################################################

DEP_FAIL_FLAG=0    #set the unmet dependency flag to "no missing deps"

# Usage:
# test_exe_exists COMMAND
#
# Example:
# if test_exe_exists wine
# then
#    ...case where the wine executable can be found...
# else
#    ...otherwise...
# fi
test_exe_exists () {
    result="`command -v "$1" 2>/dev/null`"
    if [ -n "$result" ]
    then
	echo "$1 found: $result"
	return 0
    else
	return 1
    fi
}

# Usage:
# check_program COMMAND PROGNAME
# Check that COMMAND can be found in the PATH.
# Otherwise, print an error message indicating that PROGNAME is probably not installed.
check_program () {
    if ! test_exe_exists "$1"
    then
	echo "cannot find command '$1'" 1>&2
	echo "Please make sure $2 is installed." 1>&2
	DEP_FAIL_FLAG=1;  #set the unmet dependency flag to "missing dep(s) found"
    fi
}

check_program wine Wine
check_program gcc "the GNU C compiler"
check_program cabextract cabextract
check_program gnutls-cli gnutls
check_program bison bison
check_program make make
check_program cmake cmake
check_program patch patch
check_program dbus-daemon dbus
check_program autoconf autoconf
check_program automake automake

dir_rendering="`glxinfo | grep -ie 'direct rendering'`"
printf 'glxinfo: %s\n' "$dir_rendering"
if ! echo "$dir_rendering" | grep -i yes > /dev/null 2>&1
then
    echo "\"Direct rendering\" not enabled. Please search on your distro's forum/wiki how to enable direct rendering."
    DEP_FAIL_FLAG=1
fi

if ! test_exe_exists yacc && ! test_exe_exists byacc; then
  echo "cannot find any yacc or byacc command" 1>&2
  echo "Please make sure a yacc-like parser is installed." 1>&2
  DEP_FAIL_FLAG=1
fi

if ! find /usr/lib/libfreetype* > /dev/null 2>&1; then 
  echo "\"libfreetype\" not installed.";
  DEP_FAIL_FLAG=1
fi

if [ -z "$MigrationFlag" ]
then
    DiskSpaceAvailable=$(df -BG "$Install_Location" | sed '/blocks/d' | awk '{print $4}' | awk -F'G' '{print $1}' )
    if [ "$DiskSpaceAvailable" -lt 7 ]
    then 
	echo "LoL minimum disk space requirement is 7 GiB but you only have $DiskSpaceAvailable GiB." 1>&2
	echo "Please free some space on the partition/disk that contains your $Install_location directory." 1>&2
	DEP_FAIL_FLAG=1
    else
	echo "$DiskSpaceAvailable GiB available disk space: ok"
    fi
fi

#test if any dependency is unmet
if [ $DEP_FAIL_FLAG -eq 1 ]; then
  echo "Some dependencies are not met.  Please install them and try again." 1>&2
  exit 1
fi

#################################################################################
####                                                                            #
#### end of dependency tests                                                    #
####                                                                            #
#################################################################################

#################################################################################
#download and extract the wine source                                           #
#################################################################################
winedirname="$Install_Location/wine-$Wine_version"
winetarball="$winedirname.tar.bz2"

if ! test -f "$winetarball"
then
    echo "downloading wine source into $winedirname..."
    (cd "$Install_Location" &&
	time wget --progress=dot:mega "http://sourceforge.net/projects/wine/files/Source/wine-$Wine_version.tar.bz2/download" -O "$winetarball") || exit 1
fi

echo "Extracting the Wine sources..."
(cd "$Install_Location" &&
    rm -rf "$winedirname" &&
    tar -xjf "$winetarball") || exit 1

#################################################################################
#prepare wine to be compiled                                                    #
#################################################################################
cd "$Install_Location/wine-$Wine_version"

echo "downloading Wine patch..."
if [ $winever = "1.7.1" ]; then    #check if we need the specific 1.7.1 performance patchset. Newer versions already have it
    wget --progress=dot http://www.winehq.org/pipermail/wine-devel/attachments/20130902/62c705fb/attachment-0001.bin || exit 1
    mv attachment-0001.bin cs.tar.bz2
    tar -jxf cs.tar.bz2
else
    mkdir cs
fi
cd cs
if [ $(echo $Wine_version | sed -r 's/\.//g') -le $(echo 1.7.17 | sed -r 's/\.//g') ]; then 
  wget --progress=dot http://uz.sns.it/~ranma42/iLoL/0001-HACK-Disallow-block-based-textures-with-sub-block-si.patch  || exit 1
  #wget --progress=dot http://bugs.winehq.org/attachment.cgi?id=44939 -O 0002-PandoInstallerFix.patch
else
  wget --progress=dot http://pastebin.com/raw.php?i=xSNJjkMY -O 0001-sub-block-hack.patch || exit 1
fi;
cd ..


echo "patching wine..."
#patch -p1 < 0001-HACK-Disallow-block-based-textures-with-sub-block-si.patch || exit 1
#patch -p1 < 0002-PandoInstallerFix.patch
for PATCH in $(ls -1 ./cs) ; do
  patch -p1 < ./cs/$PATCH 
done


#################################################################################
#configure and compile:                                                         #
#################################################################################
echo "configuring wine..."
echo "./configure --disable-win64 --prefix=$wineinstall"
time ./configure --disable-win64 --prefix="$wineinstall"
if [ "$?" -ne 0 ]
then
    echo "wine's configure script failed with status $?" 1>&2
    echo "You have to deal with the configure error(s) above before retrying $progname." 1>&2
    exit 1
fi

echo "This script has no error awareness: please manually check the messages above."
echo "If there are problems that need fixing, quit the script and take a look at them."
echo ""
echo "Otherwise, continue to start the compilation."
echo "The compilation can take a long time: you can go drink something (mandatory :D)"
ok_or_quit

echo "compiling wine..."

#The -j option makes 'make' to have multiple jobs (use multiple CPU cores/threads).
#For multi-core/multi-threaded CPUs this is just awesome :D
nproc="`nproc`"
if [ -n "$nproc" ]; then
    #if I find how much processors the system have, run that much jobs.
    cmd="make -j$nproc"
else
    #if I can't find the number of CPU cores/threads, default to 1 job.
    cmd=make
fi

echo "$cmd"
time $cmd || exit 1

echo "installing wine into $wineinstall"
time make install || exit 1
#clean the compiled wine folder. We don't need it anymore.
cd ..
rm -R "$Install_Location/wine-$Wine_version"

#################################################################################
#prepare the wineprefix environment                                             #
#################################################################################

if [ -z "$MigrationFlag" ] ; then

  echo "preparing the Wine Prefix environment..."
  WINE="$Install_Location/LoL_wine-$Wine_version/bin/wine"    #wine executable location

  echo "Running winecfg to set-up the wineprefix for the first time."
  echo "Accept any Gecko installation if prompted. After the winecfg window appears, just close it."
  WINEARCH=win32 "$Install_Location/LoL_wine-$Wine_version/bin/winecfg"

  #download the latest winetricks script and use it
  wget --progress=dot "http://winetricks.org/winetricks" -O ./winetricks
  chmod +x ./winetricks
  env WINE=$WINE ./winetricks winxp d3dx9 vcrun2005 vcrun2008 wininet corefonts
  "$Install_Location/LoL_wine-$Wine_version/bin/wineboot"  #reboot the wineprefix before installing LoL
  #rm ./winetricks
  
  echo "installing LoL into the virtual Windows prefix..."

  if [ -z "$Existing_LoL_Installation" ]; then
    echo "running LoL Installer..."
    # Change ulimit only for the wine command: use parentheses to create a (subshell)
    (
	ulimit -n 2048
	GC_DONT_GC=1 "$WINE" "$LoL_Installer_Location"
    )
  else
    echo "copying your existing LoL installation, please wait as this will take some time :D"
    cp -R "$Existing_LoL_Installation" "$WINEPREFIX/drive_c/"
    echo "the copy has finished."
  fi
  
fi
  
#################################################################################
#now, we're ready to create the launcher                                        #
#################################################################################
if [ -n "$MigrationFlag" ]
then
    rm -f "$launchscript"
fi

echo "creating the launcher: $launchscript..."

echo "#!/bin/bash
top='$Install_Location'
winever='$Wine_version'
"'
usage () {
    echo "Play_LeagueOfLegends.sh [OPTION...]"
    echo "Launch the League of Legends game."
    echo " Options:"
    echo "   -w      Use the rads_user_kernel.exe workaround."
    echo "           See http://appdb.winehq.org/objectManager.php?sClass=version&iId=19141"
    echo "           title: Getting the LoLClient to work!"
    echo "           date: Friday May 6th 2011, 10:22"
    echo "   -h      Show this help."
}

export WINEPREFIX="$top/LoL_Prefix"       #wineprefix location
wine="$top/LoL_wine-$winever/bin/wine"    #location of wine executable
lol="$WINEPREFIX/drive_c/Riot Games/League of Legends"
workaround=false

while getopts hw opt
do
    case "$opt" in
	h)
	    usage
	    exit 0
	    ;;
	w)
	    workaround=true
	    ;;
	"?")
	    exit 1
	    ;;
	*)
	    echo "bad option $opt" 1>&2
	    exit 1
	    ;;
    esac
done
shift "`expr $OPTIND - 1`"

if [ "$#" -ne 0 ]
then
    echo "too many arguments" 1>&2
    exit 1
fi

if $workaround
then
    # As per http://appdb.winehq.org/objectManager.php?sClass=version&iId=19141
    # "Getting the LoLClient to work!"
    # by Marcel Meißner on Friday May 6th 2011, 10:22
    # workaround for page fault in "rads_user_kernel.exe":
    cd "$lol/RADS/system"
    "$wine" rads_user_kernel.exe updateandrun lol_launcher LoLLauncher.exe > "$WINEPREFIX/wine1.log" 2>&1 & 
    sleep 5 
    cd "$lol/RADS/projects/lol_launcher/releases/0.0.0.177/deploy"
    "$wine" LoLLauncher.exe > "$WINEPREFIX/wine2.log" 2>&1 & 
else
    # This one is the default.
    cd "$lol"
    "$wine" ./lol.launcher.exe
fi' > "$launchscript"
chmod +x "$launchscript"

#################################################################################
#finalize                                                                       #
#################################################################################
echo "LoL build completed!"
echo ""
echo ""
echo "If wine created a shortcut to LoL in your desktop, delete it."
echo "To play League of Legends, use the Play_LeagueOfLegends.sh script in your desktop ;)"
echo ""
echo ""
